package com.yc.annotation.database;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MysqlTracker {
	private List<String> classNames = new ArrayList<String>();
	
	public static void main(String[] args) {
		MysqlTracker mt = new MysqlTracker();
		try {
			mt.startTacker("com.yc.mybatis.bean");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public boolean startTacker(String basePackage) throws Exception {
		URL url = this.getClass().getClassLoader().getResource(basePackage.replaceAll("\\.","/"));
		System.out.println("url="+url);
		String path = url.getPath();
		System.out.println("path="+path);
		try {
			path = URLDecoder.decode(path,"utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		System.out.println("path1="+path);
		File dest = new File(path);
		getClassInfo(basePackage , dest);
		
		classNames.forEach(System.out::println);
		
		List<String> sqlList = doTracker();
		
		Connection con = null;
		Statement stmt = null;
		
//		try {
//			Class.forName("com.mysql.jdbc.Driver");
//			String connection_url = "jdbc:mysql://127.0.0.1:3306/text?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useOldAliasMetadataBeHavior=true";
//			con = DriverManager.getConnection(connection_url,"root","a");
//			
//			for(String sql : sqlList) {
//				stmt = con.createStatement();
//				stmt.execute(sql);
//			}
//			
//			System.out.println("创建完成....");
//		} catch (ClassNotFoundException e) {
//			e.printStackTrace();
//		} catch (SQLException e) {
//			e.printStackTrace();
//		}finally {
//			if(stmt != null) {
//				stmt.close();
//			}
//			
//			if(con != null) {
//				con.close();
//			}
//		}
//		sqlList.forEach(System.out::println);
		return false;
	}

	private List<String> doTracker() throws Exception {
		if(classNames.isEmpty()) {
			return Collections.emptyList();
		}
		
		List<String> tableList = new ArrayList<String>();//建表的语句
		List<String> clist = new ArrayList<String>();  //创建约束的语句
		
		Type type = null;
		Foreignkey foreignKey = null;
		String sql = null;
		Field[] fields;
		Class<?> cls=null;
		StringBuffer sqlSbf = null;
		String tableName = null;
		String typeName = null;
		Class<?> fieldType = null;
		String temp = null;
		StringBuffer fsql = null;
		
		for(String className : classNames) {
			cls = Class.forName(className); //加载这个类
			
			//说明这个类不需要创建对应的类
			if(!cls.isAnnotationPresent(Table.class)) {
				continue;
			}
			
			sqlSbf = new StringBuffer();
			sqlSbf.append("create table ");
			
			tableName = cls.getAnnotation(Table.class).name();//获得用户指定的表名
			if(tableName == null || "".equals(tableName)) { //说明用户没有指定表名
				//则默认用类名所有字母小写为表名
				tableName = cls.getSimpleName().toLowerCase();
			}
			sqlSbf.append(tableName).append("(");  //后面开始拼接字段
			fields =cls.getDeclaredFields(); //获得类中的所有属性
			
			if(fields == null || fields.length <=0) {
				continue;
			}
			
			for(Field fd : fields) {
				if(!fd.isAnnotationPresent(Type.class) && !fd.isAnnotationPresent(PrimaryKey.class)
						 && !fd.isAnnotationPresent(Foreignkey.class)) {
					continue; //说明此属性不要生成对应的列
				}
				
				type = fd.getAnnotation(Type.class);
				sqlSbf.append(fd.getName());  //拼接列名
				
				//typeName = type.type();  //获取用户指定的类型
				if(type == null || type.type() == null || "".equals(type.type())) {
					//说明用户没有指定类型
					fieldType = fd.getType();  //或者这个属性的类型
					if(Integer.class == fieldType || Integer.TYPE == fieldType) {
						sqlSbf.append(" int ");
					}else if(Long.class == fieldType || Long.TYPE == fieldType) {
						sqlSbf.append(" bigint ");
					}else if(Double.class == fieldType || Double.TYPE == fieldType) {
						sqlSbf.append(" decimal(10,2) ");
					}else{
						sqlSbf.append(" varchar(100) ");
					}
				}else {
					typeName = type.type();
					sqlSbf.append(" ").append(typeName).append(" ");
				}
				
				//拼接约束
				if(fd.isAnnotationPresent(PrimaryKey.class)) {  //说明是主键
					sqlSbf.append("primary key");
					
					if(fd.getAnnotation(PrimaryKey.class).autoIncrement()) {//说明要自增
						sqlSbf.append(" auto_increment");
						
					}
					
				}else if(type != null) {
					if(!type.constraints().allowNull()) {
						sqlSbf.append(" not null ");
					}
					
					if(type.constraints().unique()) {
						sqlSbf.append(" unique ");
					}
					
					temp = type.constraints().defaults();
					if(temp != null && !"".equals(temp)) {  //说明有默认约束
						sqlSbf.append(" default ").append(temp);
					}
				}
				sqlSbf.append(", ");
				
				//判断这个字段有没有外键约束
				if(fd.isAnnotationPresent(Foreignkey.class)) {
					fsql = new StringBuffer();
					foreignKey = fd.getAnnotation(Foreignkey.class);
					temp = foreignKey.reference_column();  //获得引用列名
					if(temp == null || "".equals(temp)) {//说明没有指定引用的列名，则默认用属性名
						temp = fd.getName();
					}
					fsql.append("alter table ").append(tableName).append(" add constraint FK_").append(tableName).append("_")
					.append(System.currentTimeMillis()).append(" foreign key(").append(fd.getName())
					.append(") references ").append(foreignKey.reference_table()).append("(").append(temp).append(")");
					clist.add(fsql.toString());
				}
			}
			sql = sqlSbf.toString();
			sql = sql.substring(0,sql.lastIndexOf(","));
			sql +=") ENGINE=InnoDB default charset=utf8 collate=utf8_bin";
			System.out.println(sql);
			tableList.add(sql);
		}
		tableList.addAll(clist);
		return tableList;
	}

	/**
	 * 获得指定包下的所有类
	 * @param basePackage
	 * @param dest
	 */
	private void getClassInfo(String basePackage, File dest) {
		if(dest.exists() && dest.isDirectory()) {
			for(File fl : dest.listFiles()) { //遍历这个目录下的所有文件
				if(fl.isDirectory()) {
					System.out.println("++"+fl.getName());
					getClassInfo(basePackage + "." + fl.getName(), fl);
					continue;
				}
				classNames.add(basePackage + "." + fl.getName().replace(".class",""));
			}
		}
	}
}	
